﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using Liju.Model;
using LiJu.Db;
using LiJu.Product;
using Liju.Common;
using LiJu.Common;
using System.Diagnostics;
using System.Configuration;

namespace LiJu
{
    public partial class Work : Form
    {
        bool bIsHaveWeiYi = true;//是否启用位移编码器
        bool bIsHaveDianPi = true;//是否启用电批
        bool bIsHaveIO = true;//是否启用IO
        bool bIsHaveLock = true;//是否启用IO

        bool isTestWork = true;//模拟页面加载后扫码
        bool isDianJian = false;//点检中
        int nTestSN = 20;//测试SN尾号

        string strUserName;
        string strGongHao;

        /// <summary>
        /// 当前电批任务号
        /// </summary>
        public long CurrentTaskId = 1;

        /// <summary>
        /// 当日生产产品数量
        /// </summary>
        private int nToDayProductNum = 0;

        /// <summary>
        /// 当日打螺丝数量
        /// </summary>
        private int nToDayLuoSitNum = 0;

        protected Scaner scaner = null;

        /// <summary>
        /// 套筒列表
        /// </summary>
        List<SleeveModel> listSleeveModel;

        /// <summary>
        /// 套筒灯状态 -1初始化未亮 0无料红 1有料绿
        /// </summary>
        int[] arrTaoTongLEDState = { -1, -1, -1, -1 };

        /// <summary>
        /// 套筒启用状态 默认全启用 0未启用 1启用
        /// </summary>
        bool[] arrTaoTongEnable = { true, true, true, true };

        /// <summary>
        /// 套筒启用数量 默认全启用=4
        /// </summary>
        int nTaoTongEnableNum = 4;

        /// <summary>
        /// 电磁推杆设out开后 多久后out设关
        /// </summary>
        int nSetOutCloseTime = 3000;
        
        /// <summary>
        /// 电磁推杆是否已设out开状态 用于监控到指定时间后 设out关 防止过热 
        /// 0无需设out 1需设还未设out 设out时间
        /// </summary>
        string[] arrTuiGanSetOutState = { "0", "0", "0", "0" };

        /// <summary>
        /// 螺丝仓 库存型号锁等信息 ID从1开始
        /// </summary>
        List<ScrewModel> listScrewModel;

        /// <summary>
        /// 螺丝库存报警数量
        /// </summary>
        int[] arrayLuoSiWaringNum = { 0, 0, 0 };

        /// <summary>
        /// 位移坐标允许误差 百分比的数字部分 实际使用时*0.01
        /// </summary>
        double dPositionOffset = 5.0;

        /// <summary>
        /// Z轴编码器精度0.0244mm
        /// </summary>
        double dAccuracyZ = 1;

        /// <summary>
        /// XYR轴编码器精度0.005493度
        /// </summary>
        double dAccuracyXYR = 0.005493;

        /// <summary>
        /// 当前机台所在工序号
        /// </summary>
        int nGongXuNo = 1;

        /// <summary>
        /// 打螺丝Pass后是否禁用电批使能 0不禁用 1禁用
        /// </summary>
        bool bOKDianPiEnable = true;

        /// <summary>
        /// 当前处于计算螺丝下拧阶段 可记录Z最低位置 0不计 1统计 2已返回NG PASS
        /// </summary>
        int nCanFuGao = 0;

        /// <summary>
        /// 打完螺丝后最大编码器Z值
        /// </summary>
        double dLuoSiFinishZ = 0;

        /// <summary>
        /// 电批任务号 目标扭力
        /// </summary>
        float fTargetTorqueLength = 0.0f;

        /// <summary>
        /// 电批任务号 目标角度
        /// </summary>
        float fTargetAngle = 0.0f;

        /// <summary>
        /// 电批任务号 速度
        /// </summary>
        float fSpeed = 0.0f;

        /// <summary>
        /// 位移编码器坐标监控
        /// </summary>
        System.Timers.Timer timerPositionMonitor = new System.Timers.Timer();
        Thread threadPositionMonitor;

        /// <summary>
        /// 电批目标坐标
        /// </summary>
        List<double> listdPositionNeed;

        /// <summary>
        /// 点检时 等待电批返回结果线程
        /// </summary>
        Thread threadDianJianResult;
        bool bDianJianResultStop = false;

        /// <summary>
        /// IO控制器 16IN值
        /// </summary>
        bool[] arrayInValue;

        /// <summary>
        /// IO控制器 废螺丝丢进废螺丝仓监控
        /// </summary>
        System.Timers.Timer timerIOMonitor = new System.Timers.Timer();
        Thread threadIOMonitor;

        /// <summary>
        /// true 正常模式 false 测试模式
        /// </summary>
        bool bIsWorkModel = true;

        /// <summary>
        /// 作业进行中
        /// </summary>
        bool bIsWorking = false;

        /// <summary>
        /// 螺丝机1 2 是否报警
        /// </summary>
        bool bIsWarning = false;

        /// <summary>
        /// 是否可以重新送螺丝
        /// </summary>
        bool bCanReSongLuoSi = false;

        NGJudgment formNGJudgment = new NGJudgment();//异常判定窗口

        DianJian formDianJian = new DianJian();//点检窗口

        SongDingJudge formSongDingJudge = new SongDingJudge();//重新送钉判定窗口

        ProductTaskRecord productTaskRecord;//当前产品生产记录

        public Work()
        {
            InitializeComponent();
            // 加载时启用默认双缓冲并提供无闪烁的图形呈现：
            this.DoubleBuffered = true;//设置本窗体
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲
            //this.ActiveControl = null;//去掉当前控件焦点
            //SetScanerState(true);


            btStopWork.Visible = false;
            lbWorkNo.Text = lbNiuLi.Text = lbAngle.Text = lbSpeed.Text = lbTip.Text = lbScanState.Text = "";
            lbTaoTongNo.Text = "套筒序号：";
            lbLuoSiType.Text = "螺钉型号：";

            UnifiedObj.DeviceEnable[0] = bIsHaveWeiYi;
            UnifiedObj.DeviceEnable[1] = bIsHaveDianPi;
            UnifiedObj.DeviceEnable[2] = bIsHaveIO;
            UnifiedObj.DeviceEnable[3] = bIsHaveLock;
            UnifiedObj.DeviceInit();

            //设备通讯 
            DataTable dtComSet = Bll.GetComPortList();

            ////测试用 读位移编码器值
            //if (UnifiedObj.DeviceConState[0] == 1)
            //{
            //    arrayPosition = UnifiedObj.GetPosition();
            //}

            if (dtComSet.Rows.Count > 0)
            {
                if (bIsHaveDianPi)//是否使用电批
                {
                    if (LiJu.Common.Batch.ConnectionState != "连接成功")
                    {
                        //电批IP 端口
                        LiJu.Common.Batch.ipaddress = dtComSet.Rows[1]["PortName"].ToString().Trim();
                        LiJu.Common.Batch.ipport = Convert.ToInt32(dtComSet.Rows[1]["BaudRate"]);
                        //连接 开始握手并订阅结果
                        LiJu.Common.Batch.TCPConnection();
                        LiJu.Common.Batch.SetPhasesSubscribe();
                        LiJu.Common.Batch.SetLastCurve();
                        if (LiJu.Common.Batch.ConnectionState == "连接成功")
                        {
                            UnifiedObj.DeviceConState[1] = 1;
                            //禁止使能
                            LiJu.Common.Batch.DisEnable();
                            Batch.SaveCurveAction += SaveCurveData;
                        }
                        else
                        {
                            MessageBox.Show(LiJu.Common.Batch.ConnectionState);
                        }
                    }
                }
            }

            //初始化IO 重置out关
            if (UnifiedObj.DeviceEnable[2])
            {
                if (UnifiedObj.DeviceConState[2] == 1)
                {
                    for (int i = 0; i < 4; i++)//重置三色灯
                    {
                        UnifiedObj.SetOutClose(i);
                        Thread.Sleep(20);
                    }
                    for (int i = 12; i < 16; i++)//电磁杆伸出 复位
                    {
                        UnifiedObj.SetOutClose(i);
                        Thread.Sleep(20);
                    }
                    UnifiedObj.SetOutClose(20);//关送钉1
                    Thread.Sleep(20);
                    UnifiedObj.SetOutClose(21);//关送钉2
                    Thread.Sleep(20);
                }
                else
                {
                    MessageBox.Show("IO控制器连接异常。");
                }
            }

            //今日产量
            nToDayProductNum = ProductRecordDbHelper.GetProductTodayYield();
            lbProductNum.Text = nToDayProductNum.ToString();
            //今日螺丝数
            nToDayLuoSitNum = ProductTaskRecordDbHelper.GetProductTaskTodayYield();
            lbLuoSiNum.Text = nToDayLuoSitNum.ToString();

            //初始化参数 螺丝库存报警数量
            listScrewModel = ScrewDbHelper.GetScrewModelList();
            if (listScrewModel.Count > 2)
            {
                arrayLuoSiWaringNum[0] = listScrewModel[0].CapacityWarnNum;
                lbLuoSiCang1.Text = listScrewModel[0].CapacityNow.ToString();
                lbLuoSiBaoFei1.Text = "报废 " + listScrewModel[0].CapacityNGNum;

                arrayLuoSiWaringNum[1] = listScrewModel[1].CapacityWarnNum;
                lbLuoSiCang2.Text = listScrewModel[1].CapacityNow.ToString();
                lbLuoSiBaoFei2.Text = "报废 " + listScrewModel[1].CapacityNGNum;

                arrayLuoSiWaringNum[2] = listScrewModel[2].CapacityWarnNum;
                lbLuoSiCang3.Text = listScrewModel[2].CapacityNow.ToString();
                lbLuoSiBaoFei3.Text = "NG " + listScrewModel[2].CapacityNGNum;
            }

            //套筒
            listSleeveModel = Bll.GetAllSleeveModels();

            DataTable dt = BLL.Bll.GetSettingData();
            if (dt.Rows.Count > 0)
            {
                dPositionOffset = Convert.ToDouble(dt.Rows[0]["CoordinateDeviation"]);
                bOKDianPiEnable = Convert.ToBoolean(dt.Rows[0]["OKDianPiEnable"]);
                dAccuracyZ = Convert.ToDouble(dt.Rows[0]["AccuracyZ"]);
                //dAccuracyXYR = Convert.ToDouble(dt.Rows[0]["AccuracyXYR"]);
                nGongXuNo = Convert.ToInt32(dt.Rows[0]["GongXuNo"]);
                //套筒默认4个全启用 修改实际启用状态
                string[] array = dt.Rows[0]["TaoTongStateList"].ToString().Trim().Split(',');
                if (array[0] == "0")
                {
                    nTaoTongEnableNum -= 1;
                    arrTaoTongEnable[0] = false;
                }
                if (array[1] == "0")
                {
                    nTaoTongEnableNum -= 1;
                    arrTaoTongEnable[1] = false;

                }
                if (array[2] == "0")
                {
                    nTaoTongEnableNum -= 1;
                    arrTaoTongEnable[2] = false;
                }
                if (array[3] == "0")
                {
                    nTaoTongEnableNum -= 1;
                    arrTaoTongEnable[3] = false;
                }

            }
            //产品图片螺丝不能拖动
            productImgControl1.AllowDragFlag = false;
            
            //位移坐标监控程序
            timerPositionMonitor.Interval = 20;
            timerPositionMonitor.Elapsed += new System.Timers.ElapsedEventHandler(timerPositionMonitor_Elapsed);
            timerPositionMonitor.AutoReset = true; //设置一直执行(true)

            //IO控制器监控程序
            timerIOMonitor.Interval = 10;
            timerIOMonitor.Elapsed += new System.Timers.ElapsedEventHandler(timerIOMonitor_Elapsed);
            timerIOMonitor.AutoReset = true; //设置一直执行(true)

            //string strJsonPama = "{" +
            //    "\"gatewayId\":145," +
            //    "\"startTime\":\"2024-06-07 09:00:00\"," +
            //    "\"endTime\":\"2024-06-07 18:00:00\"," +
            //    "\"paraName\":\"产品区实际温度\"" +
            //"}";

            ////调外部系统接口 
            //string strReturnData = UnifiedObj.PostHtmlByJson("http://10.0.10.169:4109/noverify/influxdb/queryInfluxModel", strJsonPama);
        }

        #region 解决控件添加背景图后闪屏问题

        /// <summary>
        /// 防止闪屏
        /// </summary>
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;
                //if (this.IsXpOr2003 == true)
                //{
                //    cp.ExStyle |= 0x00080000;
                //    this.Opacity = 1;
                //}
                return cp;
            }
        }

        private Boolean IsXpOr2003
        {
            get
            {
                OperatingSystem os = Environment.OSVersion;
                Version vs = os.Version;
                if (os.Platform == PlatformID.Win32NT)
                    if ((vs.Major == 5) && (vs.Major != 0))
                        return true;
                    else
                        return false;
                else
                    return false;

            }
        }

        #endregion
		
        private void Work_Shown(object sender, EventArgs e)
        {
            strUserName = ConfigurationManager.AppSettings["UserName"];
            strGongHao = ConfigurationManager.AppSettings["UserID"];

            //非管理员 没权限 测试模式按钮隐藏
            var menuRole = PageDataDto.SystemMenuRoleInfo();
            //if (menuRole.Work_Test )//工作模式 测试模式
            //{
            //    btWorkTest.Visible = true;
            //}
            //else
            //{
            //    btWorkTest.Visible = false;
            //}
            if (menuRole.Work_DianJian)//点检
            {
                btDianJian.Visible = true;
            }
            else
            {
                btDianJian.Visible = false;
            }
            
            if (UnifiedObj.DeviceConState[0] == 1)
            {
                timerPositionMonitor.Start();
            }
            if (UnifiedObj.DeviceConState[2] == 1)
            {
                timerIOMonitor.Start();
            }
            tbSN.Focus();
        }

        /// <summary>
        /// 读取螺丝任务号参数 并显示到页面 目标扭力 目标角度 速度 
        /// </summary>
        /// <param name="nTaskNo">螺丝任务号</param>
        private void GetLuoSiParamNiuLiAngleSpeed(int nTaskNo)
        {
            //查当前螺丝参数 扭力 速度 角度 打螺丝可能有多个步骤 可能存在多个步骤有对应参数的情况 找多个步骤里最大的值
            DataTable dtLuoSiPama = BLL.Bll.GetTaskWithStep(nTaskNo);
            this.Invoke(new MethodInvoker(() =>
            {
                for (int j = 0; j < dtLuoSiPama.Rows.Count; j++)
                {
                    if (dtLuoSiPama.Rows[j]["TargetTorqueLength"] != null && !string.IsNullOrWhiteSpace(dtLuoSiPama.Rows[j]["TargetTorqueLength"].ToString()))
                    {
                        if (fTargetTorqueLength < Convert.ToSingle(dtLuoSiPama.Rows[j]["TargetTorqueLength"]))
                        {
                            fTargetTorqueLength = Convert.ToSingle(dtLuoSiPama.Rows[j]["TargetTorqueLength"]);
                            lbNiuLi.Text = dtLuoSiPama.Rows[j]["TargetTorqueLength"].ToString().Trim();//目标扭力
                        }
                    }
                    if (dtLuoSiPama.Rows[j]["Speed"] != null && !string.IsNullOrWhiteSpace(dtLuoSiPama.Rows[j]["Speed"].ToString()))
                    {
                        if (fSpeed < Convert.ToSingle(dtLuoSiPama.Rows[j]["Speed"]))
                        {
                            fSpeed = Convert.ToSingle(dtLuoSiPama.Rows[j]["Speed"]);
                            lbSpeed.Text = dtLuoSiPama.Rows[j]["Speed"].ToString().Trim();//目标速度
                        }
                    }
                    if (dtLuoSiPama.Rows[j]["TargetAngle"] != null && !string.IsNullOrWhiteSpace(dtLuoSiPama.Rows[j]["TargetAngle"].ToString()))
                    {
                        if (fTargetAngle < Convert.ToSingle(dtLuoSiPama.Rows[j]["TargetAngle"]))
                        {
                            fTargetAngle = Convert.ToSingle(dtLuoSiPama.Rows[j]["TargetAngle"]);
                            lbAngle.Text = dtLuoSiPama.Rows[j]["TargetAngle"].ToString().Trim();//目标角度
                        }
                    }
                }
            }));
        }

        /// <summary>
        /// 收到条码后 作业流程控制
        /// </summary>
        /// <param name="strSN"></param>
        protected void DoWork(string strSN)
        {
            this.ActiveControl = null;//去掉当前控件焦点
            strSN = strSN.TrimStart("\r".ToCharArray()).Trim();
            if (string.IsNullOrWhiteSpace(strSN))
            {
                return;
            }
            else if (strSN.ToLower().StartsWith("lock"))//扫的是锁的二维码 开锁
            {
                ScrewLog screwLog = new ScrewLog();
                screwLog.ScrewID = Convert.ToInt16(strSN.ToLower().Replace("lock", ""));
                screwLog.LockIO = Convert.ToInt16(strSN.ToLower().Replace("lock", ""));

                switch (screwLog.LockIO)//
                {
                    case 1://废螺丝仓 废螺丝仓开门 废螺丝数量清0
                        screwLog.ChangeType = 2;
                        screwLog.ChangeNum = Convert.ToInt32(lbLuoSiCang3.Text);
                        screwLog.ChangePreNum = screwLog.ChangeNum;
                        screwLog.ChangeLastNum = 0;
                        this.BeginInvoke(new MethodInvoker(() =>
                        {
                            listScrewModel[0].CapacityNGNum = listScrewModel[1].CapacityNGNum = listScrewModel[2].CapacityNGNum = listScrewModel[2].CapacityNow = 0;
                            lbLuoSiBaoFei1.Text = lbLuoSiBaoFei2.Text = "报废 0";
                            lbLuoSiCang3.Text = "0";
                            lbLuoSiBaoFei3.Text = "NG " + listScrewModel[1].CapacityNGNum;
                        }));
                        //更新螺丝仓NG数量
                        ScrewDbHelper.ResetLuoSiCangNgNum();
                        break;
                    case 2://螺丝仓2
                        screwLog.ChangeType = 1;
                        screwLog.ChangeNum = 0;
                        screwLog.ChangePreNum = Convert.ToInt32(lbLuoSiCang2.Text);
                        screwLog.ChangeLastNum = 0;
                        break;
                    case 3://螺丝仓1
                        screwLog.ChangeType = 1;
                        screwLog.ChangeNum = 0;
                        screwLog.ChangePreNum = Convert.ToInt32(lbLuoSiCang1.Text);
                        screwLog.ChangeLastNum = 0;
                        break;
                }
                screwLog.CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                //增加开锁记录
                ScrewLogDbHelper.ScrewLogAdd(screwLog);
                //开锁
                UnifiedObj.LockOpen(Convert.ToInt16(strSN.ToLower().Replace("lock", "")));
                return;
            }
            else if (bIsWorking)
            {
                UpdateTip("作业中，请先完成当前产品,或停止作业后，再扫码。");
                return;
            }

            //this.BeginInvoke(new MethodInvoker(() =>
            //{
            //    lbCode.Text = "条码:" + strSN;
            //}));

            //检查设备状态


            //查产品 任务信息
            string strSNType = strSN.Substring(0, 4);//前5位是型号
            ProductModel productModel = ProductDbHelper.GetProductByCode(strSNType);
            if (productModel == null)
            {
                UpdateTip("未查到此产品设置记录，请确认已添加此型号的产品信息。");
                return;
            }
            this.Invoke(new MethodInvoker(() =>
            {
                lbOrder.Text = "产品名称：" + productModel.ProductName;
            }));
            List<TaskModel> listTaskModel = TaskDbHelper.GetAllTaskByProductId(productModel.Id);
            if (listTaskModel.Count < 1)
            {
                UpdateTip("未查到此产品的任务记录，请确认已添加此型号产品的任务信息。");
                return;
            }
            List<ProductImgModel> listProductImgModel = ProductImgDbHelper.GetAllProductImgByProductId(productModel.Id);
            if (listProductImgModel.Count < 1)
            {
                UpdateTip("未查到此产品的图片，请确认已添加此型号产品的图片信息。");
                return;
            }

            //初始化产品图片
            this.Invoke(new MethodInvoker(() =>
            {
                productImgControl1.ClearData();
                productImgControl1.InitProductImg(listProductImgModel, listTaskModel);
                productImgControl1.ChangeProductImgIndex(1);
            }));

            //查产品表 是否有记录 有记录 可能是上次做到一半未完成的 接着处理 无记录从头开始
            int nProductState = 0;//当前产品生产状态
            int nWorkNo = 1;//当前任务序号 第几个螺丝 从1开始
            int nTaskStepNo = 0;//当前任务步骤号 用于任务中断后面接着执行

            ProductRecordModel productRecord = ProductRecordDbHelper.GetProductRecordInfo(strSN);
            if (productRecord != null && productRecord.State > 0)
            {
                nProductState = productRecord.State;
                nWorkNo = productRecord.WorkNo;
                nTaskStepNo = productRecord.TaskStepNo;

                switch (productRecord.State)//产品生产状态 0未开始 1PASS 2执行中 3NG
                {
                    case 1://1完成
                        this.Invoke(new MethodInvoker(() =>
                        {
                            tbSN.Text = "";
                            tbSN.Focus();
                        }));
                        UpdateTip("此产品所有任务已完成。");
                        //MessageBox.Show("此产品所有任务已完成。无需重复作业。");
                        return;
                    case 2://2执行中 接着上次步骤号执行
                        break;
                    case 3://3NG
                        this.Invoke(new MethodInvoker(() =>
                        {
                            tbSN.Text = "";
                            tbSN.Focus();
                        }));
                        UpdateTip("当前产品NG，请送维修。");
                        return;
                }
            }

            if (UnifiedObj.DeviceConState[2] == 1)
            {
                //重置套筒绿灯 红灯
                for (int i = 4; i < 11; i++)
                {
                    UnifiedObj.SetOutClose(4 + i);
                    Thread.Sleep(20);
                }
            }

            Int64 nReturn = 0;
            bIsWorking = true;

            //作业螺丝任务实体
            Int64 nProductTaskRecordID = 0;
            productTaskRecord = new ProductTaskRecord();

            for (int i = nWorkNo; i < productModel.TaskNum + 1; i++)
            {
                #region 当前螺丝设置的作业参数
                //当前套筒
                SleeveModel sleeveModelThis = listSleeveModel.Find(o => o.Id == listTaskModel[i - 1].SleeveModel);
                if (sleeveModelThis != null)
                {
                    this.Invoke(new MethodInvoker(() =>
                    {
                        lbTaoTongNo.Text = "套筒序号：" + sleeveModelThis.Model.Trim();
                    }));
                }
                //当前螺丝
                ScrewModel screwModelThis = listScrewModel.Find(o => o.Id == listTaskModel[i - 1].ScrewModel);
                if (sleeveModelThis != null)
                {
                    this.Invoke(new MethodInvoker(() =>
                    {
                        lbLuoSiType.Text = "螺钉型号：" + screwModelThis.Model.Trim();
                    }));
                }
                //当前任务号
                this.Invoke(new MethodInvoker(() =>
                {
                    btStopWork.Visible = true;
                    btDianJian.Visible = false;
                    lbTaskNo.Text = "电批任务号：" + listTaskModel[i - 1].ScrewDriverParam.ToString();
                    lbWorkNo.Text = i + " / " + productModel.TaskNum;
                }));

                //查当前螺丝参数 扭力 速度 角度 打螺丝可能有多个步骤 可能存在多个步骤有对应参数的情况 找多个步骤里最大的值
                GetLuoSiParamNiuLiAngleSpeed(listTaskModel[i - 1].ScrewDriverParam);

                //DataTable dtLuoSiPama = BLL.Bll.GetTaskWithStep(listTaskModel[i - 1].ScrewDriverParam);
                //this.Invoke(new MethodInvoker(() =>
                //{
                //    for (int j = 0; j < dtLuoSiPama.Rows.Count; j++)
                //    {
                //        if (dtLuoSiPama.Rows[j]["TargetTorqueLength"] != null && !string.IsNullOrWhiteSpace(dtLuoSiPama.Rows[j]["TargetTorqueLength"].ToString()))
                //        {
                //            if (fTargetTorqueLength < Convert.ToSingle(dtLuoSiPama.Rows[j]["TargetTorqueLength"]))
                //            {
                //                fTargetTorqueLength = Convert.ToSingle(dtLuoSiPama.Rows[j]["TargetTorqueLength"]);
                //                lbNiuLi.Text = dtLuoSiPama.Rows[j]["TargetTorqueLength"].ToString().Trim();//目标扭力
                //            }
                //        }
                //        if (dtLuoSiPama.Rows[j]["Speed"] != null && !string.IsNullOrWhiteSpace(dtLuoSiPama.Rows[j]["Speed"].ToString()))
                //        {
                //            if (fSpeed < Convert.ToSingle(dtLuoSiPama.Rows[j]["Speed"]))
                //            {
                //                fSpeed = Convert.ToSingle(dtLuoSiPama.Rows[j]["Speed"]);
                //                lbSpeed.Text = dtLuoSiPama.Rows[j]["Speed"].ToString().Trim();//目标速度
                //            }
                //        }
                //        if (dtLuoSiPama.Rows[j]["TargetAngle"] != null && !string.IsNullOrWhiteSpace(dtLuoSiPama.Rows[j]["TargetAngle"].ToString()))
                //        {
                //            if (fTargetAngle < Convert.ToSingle(dtLuoSiPama.Rows[j]["TargetAngle"]))
                //            {
                //                fTargetAngle = Convert.ToSingle(dtLuoSiPama.Rows[j]["TargetAngle"]);
                //                lbAngle.Text = dtLuoSiPama.Rows[j]["TargetAngle"].ToString().Trim();//目标角度
                //            }
                //        }
                //    }
                //}));
                #endregion

                //电批目标坐标
                listdPositionNeed = listTaskModel[i - 1].ScrewLocation.Split(',').ToList().ConvertAll(s => Convert.ToDouble(s));

                switch (nTaskStepNo)//当前任务步骤号 用于任务中断后面接着执行
                {
                    case 0:
                        #region 准备打新的螺丝任务 取套筒 至 送螺丝指令发送完成

                        //初始化 禁用电批使能
                        if (bOKDianPiEnable)
                        {
                            LiJu.Common.Batch.DisEnable();
                        }

                        this.Invoke(new MethodInvoker(() =>
                        {
                            lbResult.Text = "作业中";
                            lbResult.ForeColor = Color.White;
                            lbResult.Image = LiJu.Properties.Resources.dowork;
                            //加载产品图片 当前任务的螺钉图标 准备开始打螺丝
                            productImgControl1.SetTaskStatus(nGongXuNo, i, TestStatus.ReadyStart);
                            bCanReSongLuoSi = btReSongDing.Visible = false;
                        }));

                        //检测套筒状态 提示归还套筒 取指定套筒 套筒号从1开始
                        CheckAddOperateTaoTong(listTaskModel[i - 1].SleeveModel);

                        ////判断套筒
                        //if (UnifiedObj.DeviceConState[2] == 1)//有IO控制器
                        //{
                        //    bool[] arryTaoTong = { arrayInValue[5], arrayInValue[6], arrayInValue[7], arrayInValue[8] };
                        //    //提示需归还套筒
                        //    string strTiShi = string.Empty;
                        //    for (int m = 0; m < 4; m++)
                        //    {
                        //        //除当前要用的套筒外 其他套筒要在位
                        //        if (m != (listTaskModel[i - 1].SleeveModel - 1) && !arrayInValue[5 + m])
                        //        {
                        //            strTiShi += (m + 1) + "号 ";
                        //        }
                        //    }
                        //    if (!string.IsNullOrWhiteSpace(strTiShi))
                        //    {
                        //        UpdateTip("请将 " + strTiShi + "套筒归位。");
                        //    }

                        //    //监控其他套筒归位
                        //    while (true)
                        //    {
                        //        if (!btStopWork.Visible)//停止按钮点了后 不可见
                        //        {
                        //            bIsWorking = false;
                        //            return;
                        //        }
                        //        int nNum = 0;
                        //        for (int m = 0; m < 4; m++)
                        //        {
                        //            //除当前要用的套筒外 其他套筒要在位
                        //            if (m != (listTaskModel[i - 1].SleeveModel - 1) && arrayInValue[5 + m])
                        //            {
                        //                nNum += 1;
                        //            }
                        //        }
                        //        if (nNum == 3)//其他3个套筒在位子
                        //        {
                        //            break;
                        //        }
                        //        Thread.Sleep(200);
                        //    }

                        //    //要取的套筒亮灯
                        //    UnifiedObj.SetOutOpen(4 + listTaskModel[i - 1].SleeveModel - 1);

                        //    //当前所需套筒已用不在位子上 无需提示
                        //    if (!arrayInValue[5 + listTaskModel[i - 1].SleeveModel - 1])
                        //    {

                        //    }
                        //    else
                        //    {
                        //        UpdateTip("请取 " + listTaskModel[i - 1].SleeveModel + "号套筒");
                        //        //监控所需套筒拿走
                        //        while (true)
                        //        {
                        //            if (!btStopWork.Visible)//停止按钮点了后 不可见
                        //            {
                        //                bIsWorking = false;
                        //                return;
                        //            }
                        //            //指定套筒拿走IO=0 
                        //            if (!arrayInValue[5 + listTaskModel[i - 1].SleeveModel - 1])
                        //            {
                        //                UpdateTip(listTaskModel[i - 1].SleeveModel + "号套筒已取走。");
                        //                break;
                        //            }
                        //            Thread.Sleep(200);
                        //        }
                        //    }
                        //}
                        //else//无IO控制器 
                        //{
                        //    //提示取套筒
                        //    UpdateTip("请取 " + listTaskModel[i - 1].SleeveModel + "号套筒");
                        //    Thread.Sleep(2000);
                        //    UpdateTip("指定套筒已拿走。");
                        //    Thread.Sleep(2000);
                        //}

                        if (!btStopWork.Visible)//停止按钮点了后 不可见
                        {
                            bIsWorking = false;
                            return;
                        }
                        //新产品 或 当前步骤剩余待打螺丝>0    发送螺丝指令
                        bool bSongDing = false;
                        if (productRecord == null || productRecord.TaskStepScrewNum > 0)
                        {
                            bool bSongLuoSiSetOut = SongLuoSiSetOut(listTaskModel[i - 1].ScrewModel);
                            if (!bSongLuoSiSetOut)//送钉失败 退出
                            {
                                return;
                            }
                        }

                        //产品无生产记录 先添加主表记录
                        bool bIsAdd = true;//添加或更新 主表记录 
                        if (productRecord == null)
                        {
                            productRecord = new ProductRecordModel();
                            productRecord.ProductId = productModel.Id;
                            productRecord.ProductName = productModel.ProductName;
                            productRecord.ProductSN = strSN;

                            productRecord.TaskNum = productModel.TaskNum;
                            productRecord.ImgNum = productModel.ImgNum;
                            productRecord.OrderSN = "订单号";
                            productRecord.OrderNun = 1;
                            productRecord.Model = "产品型号";
                        }
                        else
                        {
                            bIsAdd = false;
                        }
                        productRecord.State = 2;//产品生产状态 0未开始 1PASS 2执行中 3NG
                        productRecord.WorkNo = i;//第几个螺钉
                        productRecord.TaskStepScrewNum = 1;//默认送一个钉
                        productRecord.TaskStepNo = nTaskStepNo = 1; //下一步 监控螺丝送成功
                        productRecord.GongHao = strGongHao;
                        productRecord.UserName = strUserName;
                        if (!btStopWork.Visible)//停止按钮点了后 不可见
                        {
                            bIsWorking = false;
                            return;
                        }
                        if (bIsWorkModel)//工作模式才计产量
                        {
                            if (bIsAdd)
                            {
                                nReturn = ProductRecordDbHelper.ProductRecordAdd(productRecord);
                            }
                            else
                            {
                                nReturn = ProductRecordDbHelper.ProductRecordUpdate(productRecord);
                            }
                            if (nReturn < 1)
                            {
                                UpdateTip("Error:行650 AddProductRecord添加生产记录异常。");
                                bIsWorking = false;
                                return;
                            }
                            else if (bIsAdd)//返回添加记录ID
                            {
                                productRecord.ProductRecordID = nReturn;
                            }
                        }
                        //新增打第几个螺丝记录 用螺钉数量+1
                        productTaskRecord = new ProductTaskRecord();
                        productTaskRecord.ProductRecordID = productRecord.ProductRecordID;
                        productTaskRecord.ProductName = productModel.ProductName;
                        productTaskRecord.ProductSN = strSN;
                        productTaskRecord.TaskID = listTaskModel[i - 1].Id;
                        productTaskRecord.WorkNo = i;
                        productTaskRecord.TaskImgNo = listTaskModel[i - 1].ProductImgNum;
                        productTaskRecord.State = 3;//执行结果 0未执行 1 Pass 2 NG 3执行中
                        productTaskRecord.ScrewDriverParam = listTaskModel[i - 1].ScrewDriverParam;
                        productTaskRecord.ScrewLocation = listTaskModel[i - 1].ScrewControlLocation;
                        productTaskRecord.ScrewLocationReal = "";
                        productTaskRecord.SleeveModel = listTaskModel[i - 1].SleeveModel;
                        productTaskRecord.ScrewModel = listTaskModel[i - 1].ScrewModel;
                        productTaskRecord.ScrewNum = bSongDing ? 1 : 0;//新步骤会送钉 重做可能不送钉
                        productTaskRecord.GongHao = strGongHao;
                        productTaskRecord.UserName = strUserName;

                        //读电批任务参数
                        productTaskRecord.TaskPama1 = fTargetTorqueLength.ToString();//目标扭矩
                        productTaskRecord.TaskPama2 = fTargetAngle.ToString();//目标角度
                        productTaskRecord.TaskPama3 = fSpeed.ToString();//速度
                        productTaskRecord.TaskPamaReal1 = productTaskRecord.TaskPamaReal2 = productTaskRecord.TaskPamaReal3 = "";
                        if (!btStopWork.Visible)//停止按钮点了后 不可见
                        {
                            bIsWorking = false;
                            return;
                        }
                        if (bIsWorkModel)//工作模式才计产量
                        {
                            nReturn = ProductTaskRecordDbHelper.ProductTaskRecordAdd(productTaskRecord);
                            if (nReturn < 1)
                            {
                                nProductTaskRecordID = -1;
                                UpdateTip("Error:行690 AddProductTaskRecord添加生产任务记录异常。");
                                bIsWorking = false;
                                return;
                            }
                            else
                            {
                                productTaskRecord.ProductTaskRecordID = nProductTaskRecordID = nReturn;
                            }
                        }
                        #endregion
                        //送钉指令发送完成 主表当前螺丝步骤号 TaskStepNo=nTaskStepNo 已更新为1
                        goto case 1;

                    case 1:
                        #region 实际送螺钉已完成
                        if (lbResult.Text != "作业中")
                        {
                            this.Invoke(new MethodInvoker(() =>
                            {
                                lbResult.Text = "作业中";
                                lbResult.ForeColor = Color.White;
                                lbResult.Image = LiJu.Properties.Resources.dowork;
                            }));
                        }
                        this.Invoke(new MethodInvoker(() =>
                        {
                            //加载产品图片 当前任务的螺钉图标 准备开始打螺丝
                            productImgControl1.SetTaskStatus(nGongXuNo, i, TestStatus.ReadyStart);
                            bCanReSongLuoSi = btReSongDing.Visible = true;
                        }));

                        if (bIsWorkModel && nProductTaskRecordID < 1)//异常等接着上次执行 没经过case 0 productTaskRecord 实体为空
                        {
                            productTaskRecord = ProductTaskRecordDbHelper.GetProductTaskRecord(productRecord.ProductRecordID,
                                listTaskModel[i - 1].Id, i, 3);
                            if (productTaskRecord == null)
                            {
                                UpdateTip("Error:行730 GetProductTaskRecord 未查询到数据。");
                                bIsWorking = false;
                                return;
                            }
                            else
                            {
                                nProductTaskRecordID = productTaskRecord.ProductTaskRecordID;
                            }
                        }

                        if (productRecord.TaskStepScrewNum > 0)//需要送钉才监控是否送成功
                        {
                            UpdateTip(listScrewModel[listTaskModel[i - 1].ScrewModel - 1].Model + " 送钉中...");

                            //监控实际送钉是否完成 更新页面螺丝库存 螺丝机ID 从1开始
                            SongLuoSiReal(listTaskModel[i - 1].ScrewModel);
                        }

                        //检测套筒状态 提示归还套筒 取指定套筒 套筒号从1开始
                        CheckAddOperateTaoTong(listTaskModel[i - 1].SleeveModel);

                        productTaskRecord.State = 3;//执行结果 0已送钉未执行 1 Pass 2 NG 3执行中
                        if (!btStopWork.Visible)//停止按钮点了后 不可见
                        {
                            bIsWorking = false;
                            return;
                        }
                        if (bIsWorkModel)//工作模式才计产量
                        {
                            productRecord.TaskStepNo = nTaskStepNo = 2; //下一步到 等电批返回PASS NG 
                            productRecord.TaskStepScrewNum = 0;//当前步骤已打完螺丝 剩余待打螺丝=0 
                            nReturn = ProductRecordDbHelper.ProductRecordUpdate(productRecord);
                            if (nReturn < 1)
                            {
                                UpdateTip("Error:行940 ProductRecordUpdate 作业第2步 送钉完成后更新产品记录异常。");
                                bIsWorking = false;
                                return;
                            }

                            productTaskRecord.GongHao = strGongHao;
                            productTaskRecord.UserName = strUserName;
                            productTaskRecord.UpdateTime = DateTime.Now;
                            nReturn = ProductTaskRecordDbHelper.ProductTaskRecordUpdate(productTaskRecord);
                            if (nReturn < 1)
                            {
                                UpdateTip("Error:行820 ProductTaskRecordUpdate 作业第2步 送钉完成后更新任务记录异常。");
                                bIsWorking = false;
                                return;
                            }
                        }
                        #endregion

                        //送钉完成 主表当前螺丝步骤号 TaskStepNo=nTaskStepNo 已更新为2
                        goto case 2;

                    case 2:
                        #region 移动到位 电批发指令 电批可作业

                        if (lbResult.Text != "作业中")
                        {
                            this.Invoke(new MethodInvoker(() =>
                            {
                                lbResult.Text = "作业中";
                                lbResult.ForeColor = Color.White;
                                lbResult.Image = LiJu.Properties.Resources.dowork;
                            }));
                        }
                        this.Invoke(new MethodInvoker(() =>
                        {
                            //加载产品图片 当前任务的螺钉图标 准备开始打螺丝
                            productImgControl1.SetTaskStatus(nGongXuNo, i, TestStatus.ReadyStart);
                            bCanReSongLuoSi = btReSongDing.Visible = true;
                        }));

                        if (bIsWorkModel && nProductTaskRecordID < 1)//异常等接着上次执行 没经过case 0 productTaskRecord 实体为空
                        {
                            productTaskRecord = ProductTaskRecordDbHelper.GetProductTaskRecord(productRecord.ProductRecordID,
                                listTaskModel[i - 1].Id, i, 3);
                            if (productTaskRecord == null)
                            {
                                UpdateTip("Error:行730 GetProductTaskRecord 未查询到数据。");
                                bIsWorking = false;
                                return;
                            }
                            else
                            {
                                nProductTaskRecordID = productTaskRecord.ProductTaskRecordID;
                            }
                        }

                        //检测套筒状态 提示归还套筒 取指定套筒 套筒号从1开始
                        CheckAddOperateTaoTong(listTaskModel[i - 1].SleeveModel);

                        UpdateTip("请将电批移动到：" + String.Join(",", listdPositionNeed));

                        //监控电批移动指定位置
                        while (true)
                        {
                            if (!btStopWork.Visible)//停止按钮点了后 不可见
                            {
                                bIsWorking = false;
                                return;
                            }
                            if (UnifiedObj.DeviceConState[0] == 1)//有位移传感器 移动到指定位置误差范围内
                            {
                                if (listdPositionNeed[0] >= Convert.ToDouble(UnifiedObj.arrayPosition[0]) * (1 - dPositionOffset * 0.01) &&
                                    listdPositionNeed[0] <= Convert.ToDouble(UnifiedObj.arrayPosition[0]) * (1 + dPositionOffset * 0.01) &&
                                    listdPositionNeed[1] >= Convert.ToDouble(UnifiedObj.arrayPosition[1]) * (1 - dPositionOffset * 0.01) &&
                                    listdPositionNeed[1] <= Convert.ToDouble(UnifiedObj.arrayPosition[1]) * (1 + dPositionOffset * 0.01) &&
                                    listdPositionNeed[2] >= (Convert.ToDouble(UnifiedObj.arrayPosition[2]) -
                                    (dAccuracyZ * (listScrewModel[listTaskModel[i - 1].ScrewModel - 1].ScrewLength + listTaskModel[i - 1].ErrorLimit))) * (1 - dPositionOffset * 0.01) &&
                                    listdPositionNeed[2] <= (Convert.ToDouble(UnifiedObj.arrayPosition[2]) + dAccuracyZ * listTaskModel[i - 1].ErrorLimit) * (1 + dPositionOffset * 0.01) &&
                                    listdPositionNeed[3] >= Convert.ToDouble(UnifiedObj.arrayPosition[3]) * (1 - dPositionOffset * 0.01) &&
                                    listdPositionNeed[3] <= Convert.ToDouble(UnifiedObj.arrayPosition[3]) * (1 + dPositionOffset * 0.01))
                                {
                                    UpdateTip("电批已移动到指定位置。");
                                    break;
                                }
                                Thread.Sleep(100);
                            }
                            else//无位移编码器 模拟移动到位
                            {
                                UpdateTip("电批已移动到指定位置。");
                                //MessageBox.Show("电批已移动到指定位置。");
                                Thread.Sleep(2000);
                                break;
                            }
                        }
                        
                        //发IO指令 禁用电批正反转按钮功能 马头用发TCP指令模式 无法在用IO模式实现
                        if (bIsHaveDianPi)
                        {
                            if (!btStopWork.Visible)//停止按钮点了后 不可见
                            {
                                bIsWorking = false;
                                return;
                            }
                            if (UnifiedObj.DeviceConState[1] == 1)
                            {
                                //电批移动到位 发电批参数指令                        
                                //LiJu.Common.Batch.InvokeTask(listTaskModel[i- 1].ScrewDriverParam);//更新并调用电控箱任务号
                                LiJu.Common.Batch.UseProgramIndex(listTaskModel[i - 1].ScrewDriverParam);
                                CurrentTaskId = listTaskModel[i - 1].Id;
                                //发电批使能
                                LiJu.Common.Batch.Enable();
                            }
                        }

                        //已发电批指令 更新任务状态 3执行中
                        if (bIsWorkModel && nProductTaskRecordID < 1)//异常等接着上次执行 没经过case 0 productTaskRecord 实体为空
                        {
                            if (!btStopWork.Visible)//停止按钮点了后 不可见
                            {
                                bIsWorking = false;
                                return;
                            }
                            productTaskRecord = ProductTaskRecordDbHelper.GetProductTaskRecord(productRecord.ProductRecordID,
                                listTaskModel[i - 1].Id, i, 3);
                            if (productTaskRecord == null)
                            {
                                UpdateTip("Error:行800 GetProductTaskRecord 未查询到数据。");
                                bIsWorking = false;
                                return;
                            }
                            else
                            {
                                nProductTaskRecordID = productTaskRecord.ProductTaskRecordID;
                            }
                        }
                        productTaskRecord.State = 3;//执行结果 0已送钉未执行 1 Pass 2 NG 3执行中
                        productTaskRecord.GongHao = strGongHao;
                        productTaskRecord.UserName = strUserName;
                        if (!btStopWork.Visible)//停止按钮点了后 不可见
                        {
                            bIsWorking = false;
                            return;
                        }
                        if (bIsWorkModel)//工作模式才计产量
                        {
                            productTaskRecord.GongHao = strGongHao;
                            productTaskRecord.UserName = strUserName;
                            productTaskRecord.UpdateTime = DateTime.Now;
                            productRecord.TaskStepNo = nTaskStepNo = 3; //下一步到 等电批返回PASS NG 
                            nReturn = ProductRecordDbHelper.ProductRecordUpdate(productRecord);
                            if (nReturn < 1)
                            {
                                UpdateTip("Error:行940 ProductRecordUpdate 作业第3步 发电批指令后更新产品记录异常。");
                                bIsWorking = false;
                                return;
                            }

                            nReturn = ProductTaskRecordDbHelper.ProductTaskRecordUpdate(productTaskRecord);
                            if (nReturn < 1)
                            {
                                UpdateTip("Error:行820 ProductTaskRecordUpdate 作业第3步 发电批指令后更新任务记录异常。");
                                bIsWorking = false;
                                return;
                            }
                        }
                        goto case 3;
                        #endregion
                        //移动到位 已发电批指令 主表当前螺丝步骤号 TaskStepNo=nTaskStepNo 已更新为3

                    case 3:
                        #region 等电批返回结果 判断PASS NG 若移出指定范围 禁使能 返回 case 1重新定位

                        //加载产品图片 当前任务的螺钉图标 开始打螺丝
                        this.Invoke(new MethodInvoker(() =>
                        {
                            productImgControl1.SetTaskStatus(nGongXuNo, i, TestStatus.Testing);
                            bCanReSongLuoSi = btReSongDing.Visible = true;
                        }));

                        if (bIsWorkModel && nProductTaskRecordID < 1)//异常等接着上次执行 没经过case 0 productTaskRecord 实体为空
                        {
                            productTaskRecord = ProductTaskRecordDbHelper.GetProductTaskRecord(productRecord.ProductRecordID,
                                listTaskModel[i - 1].Id, i, 2);
                            if (productTaskRecord == null)
                            {
                                UpdateTip("Error:行1010 GetProductTaskRecord 未查询到数据。");
                                bIsWorking = false;
                                return;
                            }
                            else
                            {
                                nProductTaskRecordID = productTaskRecord.ProductTaskRecordID;
                            }
                        }

                        //检测套筒状态 提示归还套筒 取指定套筒 套筒号从1开始
                        CheckAddOperateTaoTong(listTaskModel[i - 1].SleeveModel);

                        UpdateTip("请使用电批作业。");

                        nCanFuGao = 1;
                        int nReturnState = 0;//电批返回结果 0无 1Pass 2NG
                        while (true)
                        {
                            if (!btStopWork.Visible)//停止按钮点了后 不可见
                            {
                                bIsWorking = false;
                                return;
                            }

                            if (UnifiedObj.DeviceConState[0] == 1)//有位移传感器 移动到指定位置误差范围内
                            {
                                if (listdPositionNeed[0] >= Convert.ToDouble(UnifiedObj.arrayPosition[0]) * (1 - dPositionOffset * 0.01) &&
                                    listdPositionNeed[0] <= Convert.ToDouble(UnifiedObj.arrayPosition[0]) * (1 + dPositionOffset * 0.01) &&
                                    listdPositionNeed[1] >= Convert.ToDouble(UnifiedObj.arrayPosition[1]) * (1 - dPositionOffset * 0.01) &&
                                    listdPositionNeed[1] <= Convert.ToDouble(UnifiedObj.arrayPosition[1]) * (1 + dPositionOffset * 0.01) &&
                                    listdPositionNeed[2] >= (Convert.ToDouble(UnifiedObj.arrayPosition[2]) -
                                    (dAccuracyZ * (listScrewModel[listTaskModel[i - 1].ScrewModel - 1].ScrewLength + listTaskModel[i - 1].ErrorLimit))) * (1 - dPositionOffset * 0.01) &&
                                    listdPositionNeed[2] <= (Convert.ToDouble(UnifiedObj.arrayPosition[2]) + dAccuracyZ * listTaskModel[i - 1].ErrorLimit) * (1 + dPositionOffset * 0.01) &&
                                    listdPositionNeed[3] >= Convert.ToDouble(UnifiedObj.arrayPosition[3]) * (1 - dPositionOffset * 0.01) &&
                                    listdPositionNeed[3] <= Convert.ToDouble(UnifiedObj.arrayPosition[3]) * (1 + dPositionOffset * 0.01))
                                {
                                    //电批在指定范围误差内
                                    nCanFuGao = 1;
                                }
                                else//超出误差范围 禁用电批使能 跳到 case 1 重新移动到范围内
                                {
                                    if (bIsHaveDianPi)//有电批
                                    {
                                        LiJu.Common.Batch.DisEnable();
                                    }
                                    nCanFuGao = 0;
                                    dLuoSiFinishZ = 0;
                                    goto case 1;
                                }
                            }

                            if (bIsHaveDianPi)//有电批
                            {
                                if (LiJu.Common.Batch.tightenModels.Count > 0)//等待电批返回结果
                                {
                                    if (LiJu.Common.Batch.tightenModels[0].TighteningStatus == "OK")
                                    {
                                        nReturnState = 1;
                                        //禁用电批使能
                                        if (bOKDianPiEnable)
                                        {
                                            LiJu.Common.Batch.DisEnable();
                                        }
                                    }
                                    else
                                    {
                                        nReturnState = 2;
                                    }
                                    UpdateTip("");

                                    //读电批返回值 实际参数值 更新任务记录
                                    productTaskRecord.TaskPamaReal1 = LiJu.Common.Batch.tightenModels[0].Torque;//实际扭力
                                    productTaskRecord.TaskPamaReal2 = LiJu.Common.Batch.tightenModels[0].Angle;//实际角度

                                    //更新页面信息
                                    this.Invoke(new MethodInvoker(() =>
                                    {
                                        nCanFuGao = 2;//已返回电批结果 停止统计Z
                                        bCanReSongLuoSi = btReSongDing.Visible = false;
                                        lbNiuLi.Text = fTargetTorqueLength + "/" + productTaskRecord.TaskPamaReal1;//实际扭力
                                        lbAngle.Text = fTargetAngle + "/" + productTaskRecord.TaskPamaReal2;//实际角度
                                        lbSpeed.Text = fSpeed + "/" + Math.Round((dLuoSiFinishZ - listdPositionNeed[2]) * dAccuracyZ, 2) + "mm";//浮高
                                    }));
                                }
                            }
                            else//无电批调试 停2秒 返回模拟NG
                            {
                                Thread.Sleep(2000);
                                nReturnState = 2;
                                UpdateTip("");
                                bCanReSongLuoSi = false;
                                this.Invoke(new MethodInvoker(() =>
                                {
                                    btReSongDing.Visible = false;
                                }));
                            }

                            if (nReturnState > 0)
                            {
                                productTaskRecord.State = nReturnState;//执行结果 0已送钉未执行 1 Pass 2 NG 3执行中
                                productTaskRecord.GongHao = strGongHao;
                                productTaskRecord.UserName = strUserName;
                                if (!btStopWork.Visible)//停止按钮点了后 不可见
                                {
                                    bIsWorking = false;
                                    return;
                                }
                                if (bIsWorkModel)//工作模式才计产量
                                {
                                    nReturn = ProductTaskRecordDbHelper.ProductTaskRecordUpdate(productTaskRecord);
                                    if (nReturn < 1)
                                    {
                                        UpdateTip("Error:行890 ProductTaskRecordUpdate 生产任务记录更新异常。");
                                        bIsWorking = false;
                                        return;
                                    }
                                }

                                productRecord.GongHao = strGongHao;
                                productRecord.UserName = strUserName;

                                if (nReturnState == 1)//Pass
                                {
                                    if (UnifiedObj.DeviceConState[2] == 1)
                                    {
                                        UnifiedObj.SetOutOpen(2);//绿灯
                                        UnifiedObj.SetOutClose(4 + listTaskModel[i - 1].SleeveModel - 1);//重置要取的套筒out
                                    }
                                    this.Invoke(new MethodInvoker(() =>
                                    {
                                        lbResult.Text = "通过";
                                        lbResult.ForeColor = Color.White;
                                        lbResult.Image = LiJu.Properties.Resources.pass;
                                        //更新主表记录状态
                                        if (bIsWorkModel)//工作模式才计产量
                                        {
                                            nToDayLuoSitNum += 1;
                                            this.Invoke(new MethodInvoker(() =>
                                            {
                                                lbLuoSiNum.Text = nToDayLuoSitNum.ToString();
                                            }));
                                        }
                                        //打螺丝PASS 
                                        productImgControl1.SetTaskStatus(nGongXuNo, i, TestStatus.Pass);
                                    }));
                                    UpdateTip("第 " + i + " 个螺丝返回PASS.");

                                    //更新当前螺丝任务状态 
                                    if (i < productModel.TaskNum)//非最后一个螺丝 将打下一个
                                    {
                                        productRecord.WorkNo = i + 1;//接着打下一个螺丝
                                        productRecord.TaskStepScrewNum = 1;//下个步骤默认要打一个螺丝
                                    }
                                    productRecord.TaskStepNo = nTaskStepNo = 0; //新螺丝步骤从头开始
                                    if (!btStopWork.Visible)//停止按钮点了后 不可见
                                    {
                                        return;
                                    }
                                    if (bIsWorkModel)//工作模式才计产量
                                    {
                                        nReturn = ProductRecordDbHelper.ProductRecordUpdate(productRecord);
                                        if (nReturn < 1)
                                        {
                                            UpdateTip("Error:行940 ProductRecordUpdate 作业第4步 电批返回PASS 更新产品记录异常。");
                                            bIsWorking = false;
                                            return;
                                        }
                                    }
                                    Thread.Sleep(2000);
                                    nCanFuGao = 0;
                                    dLuoSiFinishZ = 0;
                                    break;
                                }
                                else//电批打螺丝NG 弹品质页面
                                {
                                    if (UnifiedObj.DeviceConState[2] == 1)
                                    {
                                        UnifiedObj.SetOutOpen(0);//红灯
                                    }
                                    this.Invoke(new MethodInvoker(() =>
                                    {
                                        //打螺丝NG
                                        lbResult.Text = "NG";
                                        lbResult.ForeColor = Color.White;
                                        lbResult.Image = LiJu.Properties.Resources.ng;

                                        productImgControl1.SetTaskStatus(nGongXuNo, i, TestStatus.NG);
                                    }));
                                    UpdateTip("第 " + i + " 个螺丝返回NG.");

                                    //更新当前螺丝任务状态 
                                    productRecord.TaskStepNo = nTaskStepNo = 4; //NG弹品质异常判定页面
                                    if (!btStopWork.Visible)//停止按钮点了后 不可见
                                    {
                                        bIsWorking = false;
                                        return;
                                    }
                                    if (bIsWorkModel)//工作模式才计产量
                                    {
                                        nReturn = ProductRecordDbHelper.ProductRecordUpdate(productRecord);
                                        if (nReturn < 1)
                                        {
                                            UpdateTip("Error:行970 ProductRecordUpdate 作业第4步 电批返回NG 更新产品记录异常。");
                                            bIsWorking = false;
                                            return;
                                        }
                                    }
                                    Thread.Sleep(200);

                                    goto case 4;
                                }
                            }
                            else//未获取到电批返回结果 
                            {
                                Thread.Sleep(20);
                            }
                        }
                        break;
                        #endregion
                        //PASS 打下个螺丝 NG跳case 4

                    case 4:
                        #region NG弹品质异常处理 更新任务记录
                        if (!btStopWork.Visible)//停止按钮点了后 不可见
                        {
                            return;
                        }
                        if (lbResult.Text != "NG")
                        {
                            this.Invoke(new MethodInvoker(() =>
                            {
                                lbResult.Text = "NG";
                                lbResult.ForeColor = Color.White;
                                lbResult.Image = LiJu.Properties.Resources.ng;
                            }));
                        }
                        UpdateTip("请判定当前异常原因。");
                        if (bIsWorkModel && nProductTaskRecordID < 1)//异常等接着上次执行 没经过case 0 productTaskRecord 实体为空
                        {
                            productTaskRecord = ProductTaskRecordDbHelper.GetProductTaskRecord(productRecord.ProductRecordID,
                                listTaskModel[i - 1].Id, i, 2);
                            if (productTaskRecord == null)
                            {
                                UpdateTip("Error:行1010 GetProductTaskRecord 未查询到数据。");
                                bIsWorking = false;
                                return;
                            }
                            else
                            {
                                nProductTaskRecordID = productTaskRecord.ProductTaskRecordID;
                            }
                        }
                        this.Invoke(new MethodInvoker(() =>
                        {
                            bCanReSongLuoSi = btReSongDing.Visible = false;
                            if (formNGJudgment.Visible == false)
                            {
                                formNGJudgment.nReDoSongDing = -1;
                                formNGJudgment.bIsWorkModel = bIsWorkModel;
                                formNGJudgment.productTaskRecordNG = productTaskRecord;
                                formNGJudgment.ShowDialog();
                            }
                        }));

                        //等品质判定异常结果
                        while (true)
                        {
                            if (!btStopWork.Visible)//停止按钮点了后 不可见
                            {
                                bIsWorking = false;
                                return;
                            }
                            if (formNGJudgment.nCheckState > 0)
                            {
                                break;
                            }
                            Thread.Sleep(100);
                        }
                        //4品质判定PASS 5品质判定NG 6品质判定重做
                        if (formNGJudgment.nCheckState == 4)//品质判定pass 
                        {
                            if (UnifiedObj.DeviceConState[2] == 1)
                            {
                                UnifiedObj.SetOutClose(0);//红灯
                                Thread.Sleep(20);
                                UnifiedObj.SetOutOpen(2);//绿灯
                                Thread.Sleep(20);
                                UnifiedObj.SetOutClose(4 + listTaskModel[i - 1].SleeveModel - 1);//重置要取的套筒out
                            }
                            this.Invoke(new MethodInvoker(() =>
                            {
                                lbResult.Text = "通过";
                                lbResult.ForeColor = Color.White;
                                lbResult.Image = LiJu.Properties.Resources.pass;
                                UpdateTip("");
                                //更新主表记录状态
                                if (bIsWorkModel)//工作模式才计产量
                                {
                                    nToDayLuoSitNum += 1;
                                    this.Invoke(new MethodInvoker(() =>
                                    {
                                        lbLuoSiNum.Text = nToDayLuoSitNum.ToString();
                                    }));
                                }
                            }));
                            while (true)
                            {
                                for (int m = 0; m < 10; m++)
                                {
                                    Thread.Sleep(50);
                                }
                                break;
                            }
                            if (i < productModel.TaskNum)
                            {
                                productRecord.WorkNo = i + 1;//接着打下一个螺丝
                                productRecord.TaskStepScrewNum = 1;//下个步骤默认要打一个螺丝
                            }
                            productRecord.TaskStepNo = nTaskStepNo = 0; //新螺丝步骤从头开始
                            productImgControl1.SetTaskStatus(nGongXuNo, i, TestStatus.Pass);
                        }
                        else
                        {
                            //ng 重打并需要重新送钉 原来螺丝报废 不送钉 原螺丝认为可继续用不算报废 更新页面对应螺钉仓 废螺丝数量
                            if (formNGJudgment.nCheckState == 5 || formNGJudgment.nReDoSongDing == 1)
                            {
                                this.Invoke(new MethodInvoker(() =>
                                {
                                    if (listTaskModel[i - 1].ScrewModel == 1)
                                    {
                                        listScrewModel[0].CapacityNGNum += 1;
                                        lbLuoSiBaoFei1.Text = "报废 " + listScrewModel[0].CapacityNGNum;
                                    }
                                    else
                                    {
                                        listScrewModel[1].CapacityNGNum += 1;
                                        lbLuoSiBaoFei2.Text = "报废 " + listScrewModel[1].CapacityNGNum;
                                    }
                                    listScrewModel[2].CapacityNGNum += 1;
                                    lbLuoSiBaoFei3.Text = "NG " + listScrewModel[2].CapacityNGNum;

                                    //NG螺钉应丢进废螺丝仓数量+1
                                    nReturn = ScrewDbHelper.ScrewModelNGNumAdd(Convert.ToInt32(listTaskModel[i - 1].ScrewModel));
                                    if (nReturn < 1)
                                    {
                                        UpdateTip("Error:行1080 ScrewModelNGNumAddNG 螺钉应丢进废螺丝仓数量+1执行异常。");
                                        bIsWorking = false;
                                        return;
                                    }
                                }));
                            }

                            if (UnifiedObj.DeviceConState[2] == 1)//重置要取的套筒out
                            {
                                UnifiedObj.SetOutClose(4 + listTaskModel[i - 1].SleeveModel - 1);
                            }

                            if (formNGJudgment.nCheckState == 5)//品质判定ng 终止此产品作业
                            {
                                productRecord.State = 3;
                                productRecord.TaskStepScrewNum = 0;
                            }
                            else//重新打螺丝 当前螺丝任务标记重做 新增新螺丝记录
                            {
                                i -= 1;//重新打螺丝
                                if (formNGJudgment.nReDoSongDing == 1)
                                {
                                    productRecord.TaskStepScrewNum = 1;
                                    productRecord.TaskStepNo = nTaskStepNo = 0; //步骤从头开始
                                }
                                else
                                {
                                    productRecord.TaskStepScrewNum = 0;
                                    productRecord.TaskStepNo = nTaskStepNo = 1; //不重新打螺丝
                                }
                            }
                        }
                        nCanFuGao = 0;
                        dLuoSiFinishZ = 0;
                        //更新主表记录状态  
                        productRecord.GongHao = strGongHao;
                        productRecord.UserName = strUserName;
                        if (bIsWorkModel)//工作模式才计产量
                        {
                            nReturn = ProductRecordDbHelper.ProductRecordUpdate(productRecord);
                            if (nReturn < 1)
                            {
                                UpdateTip("Error:行1100 ProductRecordUpdate 更新产品记录NG 当前螺丝第5步 更新异常。");
                                bIsWorking = false;
                                return;
                            }
                        }
                        break;
                        #endregion
                }
                if (UnifiedObj.DeviceConState[2] == 1)//打完螺丝关灯
                {
                    UnifiedObj.SetOutClose(0);//红灯
                    UnifiedObj.SetOutClose(2);//绿灯
                }
                if (productRecord.State == 3)//产品最终判定NG 作业完成
                {
                    UpdateTip("当前产品NG，请送维修。");
                    bIsWorking = false;
                    this.Invoke(new MethodInvoker(() =>
                    {
                        btStopWork.Visible = false;
                        tbSN.Text = "";
                        tbSN.Focus();
                    }));
                    return;
                }
                //打完所有螺丝后 更新主表状态
                if (i == productModel.TaskNum)
                {
                    bIsWorking = false;
                    this.Invoke(new MethodInvoker(() =>
                    {
                        tbSN.Text = "";
                        tbSN.Focus();
                        btStopWork.Visible = false;
                    }));
                    productRecord.State = 1;
                    productRecord.TaskStepScrewNum = 0;
                    if (bIsWorkModel)//工作模式才计产量
                    {
                        nReturn = ProductRecordDbHelper.ProductRecordUpdate(productRecord);

                        if (nReturn < 1)
                        {
                            UpdateTip("Error:行1120 ProductRecordUpdate 打完所有螺丝 更新产品记录PASS 更新异常。");
                            return;
                        }
                        else
                        {
                            nToDayProductNum += 1;
                            this.Invoke(new MethodInvoker(() =>
                            {
                                lbProductNum.Text = nToDayProductNum.ToString();
                            }));
                        }
                    }
                    UpdateTip("当前产品已完成。");
                    this.Invoke(new MethodInvoker(() =>
                    {
                        btDianJian.Visible = true;
                        btDianJian.Text = "开始点检";
                        tbSN.Focus();
                    }));
                }
            }
        }


        /// <summary>
        /// 获取设备连接状态 0力臂 1电批 2套筒 3上料机
        /// </summary>
        /// <returns></returns>
        private bool GetDeviceState()
        {

            return true;
        }

        /// <summary>
        /// 保存曲线扭矩和角度数据
        /// </summary>
        /// <param name="torques"></param>
        /// <param name="angles"></param>
        private void SaveCurveData(List<double> torques, List<double> angles, double spendTime)
        {
            try
            {
                string torqueStr = String.Join(",", torques);
                string angleStr = String.Join(",", angles);
                CurveModel curveModel = new CurveModel()
                {
                    TaskId = CurrentTaskId,
                    Torques = torqueStr,
                    Angles = angleStr,
                    TimeSpan = spendTime
                };
                bool result = CurveDbHelper.AddCurve(curveModel);
            }
            catch (Exception ex)
            {

                Debug.WriteLine($"SaveCurveData->{ex.Message}");
            }

        }

        /// <summary>
        /// 切换工作模式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btWork_Click(object sender, EventArgs e)
        {
            //需完成当前产品才能切换工作模式
            if (!bIsWorking)
            {
                if ((bIsWorkModel && ((Button)sender).Text == "工作模式")||
                    (!bIsWorkModel && ((Button)sender).Text == "测试模式"))
                {
                    return;
                }
                if (bIsWorkModel)//工作模式切换为测试模式
                {
                    bIsWorkModel = false;
                    btWork.BackgroundImage = LiJu.Properties.Resources.gognzuo;
                    btWorkTest.BackgroundImage = LiJu.Properties.Resources.ceshi2;
                    MessageBox.Show("测试模式，将不计产品的产量。");
                }
                else
                {
                    bIsWorkModel = true;
                    btWork.BackgroundImage = LiJu.Properties.Resources.gongzuo2;
                    btWorkTest.BackgroundImage = LiJu.Properties.Resources.ceshi;
                }
            }
            else
            {
                MessageBox.Show("作业中，请先完成当前产品，再切换工作模式。");
                this.ActiveControl = null;//去掉当前控件焦点
            }

        }

        /// <summary>
        /// 获取当前位移编码器位置
        /// </summary>
        /// <returns></returns>
        private void GetPositionNow()
        {
            //获取当前电批位置 更新页面坐标
            if (UnifiedObj.DeviceConState[0] == 1)
            {
                //读取编码器值
                UnifiedObj.GetPosition();

                //可计算浮高时 统计编码器Z最大值
                if (nCanFuGao == 1 && dLuoSiFinishZ > UnifiedObj.arrayPosition[2])
                {
                    dLuoSiFinishZ = UnifiedObj.arrayPosition[2];
                }

                this.BeginInvoke((Action)delegate ()
                {
                    lbPositionNow.Text = "电批当前位置：" + UnifiedObj.arrayPosition[0] + ", " + UnifiedObj.arrayPosition[1] + ", " +
                        UnifiedObj.arrayPosition[2] + ", " + UnifiedObj.arrayPosition[3];
                });
            }
            timerPositionMonitor.Start();
        }

        //位移编码器监控程序
        public void timerPositionMonitor_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            timerPositionMonitor.Stop();

            //须从UI线程另启动一个线程,在新线程调用异步刷新提示信息
            threadPositionMonitor = new Thread(new ThreadStart(GetPositionNow));
            threadPositionMonitor.IsBackground = true;
            threadPositionMonitor.Start();
        }

        //IO控制器监控
        public void timerIOMonitor_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            timerIOMonitor.Stop();

            //须从UI线程另启动一个线程,在新线程调用异步刷新提示信息
            threadIOMonitor = new Thread(new ThreadStart(IOMonitor));
            threadIOMonitor.IsBackground = true;
            threadIOMonitor.Start();
        }

        /// <summary>
        /// 上一个废螺丝感应IO值 0初始化 1是 2否
        /// </summary>
        int nIsFeiLuoSiRre = 0;

        /// <summary>
        /// IO控制器监控 丢废螺丝监控
        /// </summary>
        private void IOMonitor()
        {
            if (UnifiedObj.DeviceConState[2] == 0)
            {
                return;
            }
            //IO控制器16IN值
            arrayInValue = UnifiedObj.GetInAllValue();
            if (!bIsWarning && (arrayInValue[5] || arrayInValue[7]))//螺丝机1 2报警 亮黄灯
            {
                bIsWarning = true;
                UnifiedObj.SetOutOpen(1);
            }
            else if (bIsWarning && !arrayInValue[5] && !arrayInValue[7])//没报警 灭黄灯
            {
                bIsWarning = false;
                UnifiedObj.SetOutClose(1);
            }
            

            for (int i = 0; i < 4; i++)
            {
                if (arrTuiGanSetOutState[i] == "1")//电磁推杆需设out开状态
                {
                    UnifiedObj.SetOutOpen(12 + i);
                    arrTuiGanSetOutState[i] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");//电磁推杆设out开的时间
                    Thread.Sleep(20);
                }

                //套筒到位状态变化
                if (arrayInValue[0 + i] && arrTaoTongLEDState[0 + i] != 1)//套筒在位
                {
                    arrTaoTongLEDState[0 + i] = 1;

                    ////套筒电磁推杆弹出
                    //UnifiedObj.SetOutClose(12 + i);
                    //arrTuiGanSetOutState[i] = "0";
                    //Thread.Sleep(20);

                    UnifiedObj.SetOutClose(8 + i);// 关红灯
                    Thread.Sleep(20);
                    UnifiedObj.SetOutOpen(4 + i);// 亮绿灯
                }
                else if (!arrayInValue[0 + i] && arrTaoTongLEDState[0 + i] != 0)//套筒不在位
                {
                    arrTaoTongLEDState[0 + i] = 0;
                    UnifiedObj.SetOutClose(4 + i);// 关绿灯
                    Thread.Sleep(20);
                    UnifiedObj.SetOutOpen(8 + i);// 亮红灯
                }
                
                //套筒电磁推杆弹出 超过指定时间 缩回 防止过热
                if (arrTuiGanSetOutState[i] != "0" && arrTuiGanSetOutState[i] != "1" &&
                    (DateTime.Now - Convert.ToDateTime(arrTuiGanSetOutState[i])).TotalMilliseconds > nSetOutCloseTime)
                {
                    //套筒电磁推杆弹出
                    UnifiedObj.SetOutClose(12 + i);
                    arrTuiGanSetOutState[i] = "0";
                    Thread.Sleep(20);
                }
            }

            //废螺丝IO=0是感应到有料 且与上一个信号不一样有变化
            if (arrayInValue[8] && nIsFeiLuoSiRre != 1)
            {
                if (formSongDingJudge.nState == 1)//重新送钉判定要送
                {
                    formSongDingJudge.nState = 3;//感应到已丢废螺丝
                }
                //更新页面废螺钉库存
                this.Invoke(new MethodInvoker(() =>
                {
                    //NG螺钉实际丢进废弃螺钉仓数量+1
                    int nReturn = ScrewDbHelper.ScrewModelNGNumRealAdd();
                    if (nReturn < 1)
                    {
                        UpdateTip("Error:行1290 ScrewModelNGNumRealAdd NG螺钉实际丢进废弃螺钉仓数量 更新异常。");
                        return;
                    }

                    listScrewModel[2].CapacityNow += 1;
                    lbLuoSiCang3.Text = listScrewModel[2].CapacityNow.ToString();

                    //库存报警
                    if (listScrewModel[2].CapacityNow >= arrayLuoSiWaringNum[2])
                    {
                        lbLuoSiCang3.ForeColor = Color.Gold;
                    }
                    else
                    {
                        lbLuoSiCang3.ForeColor = Color.White;
                    }
                }));
            }
            nIsFeiLuoSiRre = arrayInValue[8] ? 1 : 2;
            timerIOMonitor.Start();
        }

        /// <summary>
        /// 更新提示信息 1提示信息 2 3
        /// </summary>
        private void UpdateTip(string strMesage, int nType = 1)
        {
            try
            {
                if (this.IsHandleCreated)
                {
                    this.Invoke((Action)delegate ()
                    {
                        lbTip.Text = strMesage;
                    });
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// 设置扫码枪监视状态
        /// </summary>
        protected virtual void SetScanerState(bool bIsStart)
        {
            if (bIsStart)//启用
            {
                this.KeyPreview = true;
                this.KeyUp += Form_KeyUp;

                if (scaner == null)
                {
                    scaner = new Scaner();
                    scaner.ScanerReceived += ScanDoWork;
                }
            }
            else//停用
            {
                this.KeyUp -= Form_KeyUp;
                this.KeyPreview = false;

                if (scaner != null)
                {
                    scaner.ScanerReceived -= ScanDoWork;
                    scaner = null;
                }
            }
        }

        /// <summary>
        /// 按键抬起事件处理过程，用于截获扫码枪消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void Form_KeyUp(object sender, KeyEventArgs e)
        {
            scaner.Add(e.KeyCode);
            Task.Run(() =>
            {
                DoWork(tbSN.Text.Trim());
            });

        }

        private void LbProductNum_Click(object sender, EventArgs e)
        {
            Thread tr = new Thread(new ThreadStart(test));
            tr.IsBackground = true;
            tr.Start();

        }

        private void test()
        {
            if (isTestWork)//模拟页面加载后扫码
            {
                DoWork("100110" + nTestSN);
                nTestSN += 1;
                return;
            }
        }

        private void ScanDoWork(string strSN)
        {
            Task.Run(() =>
            {
                DoWork(strSN);
            });
        }

        /// <summary>
        /// 停止作业
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtStopWork_Click(object sender, EventArgs e)
        {
            if (btStopWork.Visible)
            {
                bIsWorking = false;
                btStopWork.Visible = false;
                btDianJian.Visible = true;
                btReSongDing.Visible = false;
                lbResult.Text = "待扫码";
                lbResult.ForeColor = Color.Chocolate;
                lbResult.Image = LiJu.Properties.Resources.dowork;
                UpdateTip("");
                tbSN.Text = "";
                tbSN.Focus();
            }
        }

        //螺丝机1送钉
        private void Label13_Click(object sender, EventArgs e)
        {
            if (UnifiedObj.SetOutOpen(20))
            {
                Thread.Sleep(200);
                UnifiedObj.SetOutClose(20);
                //MessageBox.Show("true");
            }
            else
            {
                //MessageBox.Show("false");
            }
        }

        //螺丝机2送钉
        private void Label14_Click(object sender, EventArgs e)
        {
            if (UnifiedObj.SetOutOpen(21))
            {
                Thread.Sleep(200);
                UnifiedObj.SetOutClose(21);
            }
            else
            {
                //MessageBox.Show("false");
            }
        }

        /// <summary>
        /// 套筒卡子缩回 弹出逻辑状态 即发的是缩回/弹出指令
        /// </summary>
        bool[] bTaoTongKaState = { false, false, false, false };

        /// <summary>
        /// 检测套筒状态 提示归还套筒 取指定套筒 套筒号从1开始
        /// </summary>
        /// <param name="nTaoTongNo"></param>
        private void CheckAddOperateTaoTong(int nTaoTongNo)
        {
            //判断套筒
            if (UnifiedObj.DeviceConState[2] == 1)//有IO控制器
            {
                bool[] arryTaoTong = { arrayInValue[0], arrayInValue[1], arrayInValue[2], arrayInValue[3] };
                //提示需归还套筒
                string strTiShi = string.Empty;
                for (int m = 0; m < 4; m++)
                {
                    //当前套筒启用 且 除当前要用的套筒外 其他套筒要在位
                    if (arrTaoTongEnable[m] &&  m != (nTaoTongNo - 1) && !arrayInValue[m])
                    {
                        strTiShi += (m + 1) + "号 ";
                        arrTuiGanSetOutState[m] = "1";
                    }
                }
                if (!string.IsNullOrWhiteSpace(strTiShi))
                {
                    UpdateTip("请将 " + strTiShi + "套筒归位。");
                }

                //间隔3秒 方便切换套筒操作
                DateTime dtFrom = DateTime.Now;
                while (true)
                {
                    if ((DateTime.Now - dtFrom).TotalSeconds > 1)
                    {
                        break;
                    }
                    Thread.Sleep(200);
                }

                //监控其他套筒归位
                while (true)
                {
                    if (!btStopWork.Visible)//停止按钮点了后 不可见
                    {
                        bIsWorking = false;
                        return;
                    }
                    int nNum = 0;
                    for (int m = 0; m < 4; m++)
                    {
                        //当前套筒启用 且 除当前要用的套筒外 其他套筒要在位
                        if (arrTaoTongEnable[m] && m != (nTaoTongNo - 1) && arrayInValue[m])
                        {
                            nNum += 1;
                        }
                    }
                    if (nNum == nTaoTongEnableNum - 1)//除当前要用的套筒 其他启用的套筒都在位子
                    {
                        break;
                    }
                    Thread.Sleep(200);
                }

                ////要取的套筒亮灯
                //UnifiedObj.SetOutOpen(4 + nTongTongNo - 1);

                //当前所需套筒已用不在位子上 无需提示
                if (!arrayInValue[ nTaoTongNo - 1])
                {

                }
                else
                {
                    UpdateTip("请取 " + nTaoTongNo + "号套筒");

                    //间隔3秒 方便切换套筒操作
                    dtFrom = DateTime.Now;
                    while (true)
                    {
                        if ((DateTime.Now - dtFrom).TotalSeconds > 1)
                        {
                            break;
                        }
                        Thread.Sleep(200);
                    }

                    bool bHaveSetOut = false;
                    //DateTime dtFrom = DateTime.Now;
                    //监控所需套筒拿走
                    while (true)
                    {
                        if (!btStopWork.Visible)//停止按钮点了后 不可见
                        {
                            bIsWorking = false;
                            return;
                        }
                        //if ((DateTime.Now - dtFrom).TotalMilliseconds > nSetOutCloseTime)
                        //{
                        //    //套筒电磁推杆缩回 超过指定时间 防止过热
                        //    UnifiedObj.SetOutClose(12 + nTaoTongNo - 1);
                        //    Thread.Sleep(50);
                        //}

                        //要取的套筒灭绿灯 闪灭效果
                        UnifiedObj.SetOutClose(4 + nTaoTongNo - 1);
                        Thread.Sleep(200);

                        //要取的套筒亮绿灯 闪灭效果
                        UnifiedObj.SetOutOpen(4 + nTaoTongNo - 1);
                        Thread.Sleep(200);

                        if (!bHaveSetOut)
                        {
                            bHaveSetOut = true;
                            //套筒电磁推杆需缩回
                            SetTuiGanSuoHui(nTaoTongNo);
                        }

                        //指定套筒拿走IO=0 拿走后灭绿灯 亮红灯 在IO监控中会改变
                        if (!arrayInValue[ nTaoTongNo - 1])
                        {
                            ////套筒电磁推杆弹出
                            //UnifiedObj.SetOutOpen(12 + nTaoTongNo - 1);
                            //Thread.Sleep(50);
                            ////要取的套筒灭绿灯
                            //UnifiedObj.SetOutClose(4 + nTaoTongNo - 1);
                            //Thread.Sleep(50);
                            ////要取的套筒亮红灯 
                            //UnifiedObj.SetOutOpen(8 + nTaoTongNo - 1);
                            //Thread.Sleep(50);
                            UpdateTip(nTaoTongNo + "号套筒已取走。");
                            break;
                        }
                    }
                }
            }
            else//无IO控制器 
            {
                //提示取套筒
                UpdateTip("请取 " + nTaoTongNo + "号套筒");
                Thread.Sleep(2000);
                UpdateTip(nTaoTongNo + "号套筒已拿走。");
                Thread.Sleep(2000);
            }
        }

        //点检
        private void BtDianJian_Click(object sender, EventArgs e)
        {
            if (bIsWorking)
            {
                UpdateTip("作业中，请先完成当前产品,或停止作业后，再点检。");
                return;
            }

            if (!isDianJian)
            {
                isDianJian = true;
                this.Invoke(new MethodInvoker(() =>
                {
                    lbResult.Text = "";
                    lbResult.ForeColor = Color.Chocolate;
                    lbResult.Image = LiJu.Properties.Resources.dowork;
                    btDianJian.Text = "点检结束";
                    formDianJian.ShowDialog();
                }));

                //等点检设置完成
                while (true)
                {
                    if (formDianJian.nDianJianState > 0)
                    {
                        break;
                    }
                    Thread.Sleep(100);
                }
                //取消电检
                if (formDianJian.nDianJianState == 2)
                {
                    //重置状态
                    isDianJian = false;
                    formDianJian.nDianJianState = 0;
                    formDianJian.nSleeveModelID = 0;
                    formDianJian.nDianJianLuoSiPamar = 0;
                    btDianJian.Text = "开始点检";
                    tbSN.Focus();
                    return;
                }
                //检测套筒状态 提示归还套筒 取指定套筒 套筒号从1开始
                CheckAddOperateTaoTong(formDianJian.nSleeveModelID);

                //发IO指令 禁用电批正反转按钮功能 马头用发TCP指令模式 无法在用IO模式实现
                if (UnifiedObj.DeviceConState[1] == 1)
                {
                    //电批移动到位 发电批参数指令                        
                    //LiJu.Common.Batch.InvokeTask(listTaskModel[i- 1].ScrewDriverParam);//更新并调用电控箱任务号
                    LiJu.Common.Batch.UseProgramIndex(formDianJian.nDianJianLuoSiPamar);
                    //发电批使能
                    LiJu.Common.Batch.Enable();

                    //读取螺丝任务号参数 并显示到页面 目标扭力 目标角度 速度 
                    GetLuoSiParamNiuLiAngleSpeed(formDianJian.nDianJianLuoSiPamar);

                    //等电批返回结果
                    bDianJianResultStop = false;
                    threadDianJianResult = new Thread(new ThreadStart(GetDianJianDianPiResult));
                    threadDianJianResult.IsBackground = true;
                    threadDianJianResult.Start();

                }
            }
            else
            {
                bDianJianResultStop = true;
                //等线程停止
                threadDianJianResult.Join();

                if (UnifiedObj.DeviceConState[1] == 1)
                {
                    //电批禁用使能
                    LiJu.Common.Batch.DisEnable();
                }
                //重置状态
                isDianJian = false;
                formDianJian.nDianJianState = 0;
                formDianJian.nSleeveModelID = 0;
                formDianJian.nDianJianLuoSiPamar = 0;
                btDianJian.Text = "开始点检";
                tbSN.Focus();
            }
        }

        /// <summary>
        /// 点检设置后 等待电批返回结果
        /// </summary>
        private void GetDianJianDianPiResult()
        {
            DateTime dtFrom = DateTime.Now;
            int nReturnState = 0;//电批返回结果 0无 1Pass 2NG
            while (!bDianJianResultStop)
            {
                if ((DateTime.Now - dtFrom).TotalSeconds > 60)
                {
                    //重置状态
                    isDianJian = false;
                    formDianJian.nDianJianState = 0;
                    formDianJian.nSleeveModelID = 0;
                    formDianJian.nDianJianLuoSiPamar = 0;
                    btDianJian.Text = "开始点检";
                    UpdateTip("1分钟内未点检，或未收到电批返回结果，若需要可重新点检。");
                    break;
                }
                if (bIsHaveDianPi)//有电批
                {
                    if (LiJu.Common.Batch.tightenModels.Count > 0)//等待电批返回结果
                    {
                        if (LiJu.Common.Batch.tightenModels[0].TighteningStatus == "OK")
                        {
                            nReturnState = 1;
                        }
                        else
                        {
                            nReturnState = 2;
                        }
                        UpdateTip("");

                        //更新页面信息
                        this.Invoke(new MethodInvoker(() =>
                        {
                            if (LiJu.Common.Batch.tightenModels.Count > 0)
                            {
                                lbNiuLi.Text = fTargetTorqueLength + "/" + LiJu.Common.Batch.tightenModels[0].Torque;//实际扭力
                                lbAngle.Text = fTargetAngle + "/" + LiJu.Common.Batch.tightenModels[0].Angle;//实际角度
                            }
                        }));
                    }
                }
                else//无电批调试 停2秒 返回模拟NG
                {
                    nReturnState = 2;
                    UpdateTip("");
                }

                if (nReturnState > 0)
                {
                    if (nReturnState == 1)//Pass
                    {
                        if (UnifiedObj.DeviceConState[2] == 1)
                        {
                            UnifiedObj.SetOutClose(4 + formDianJian.nSleeveModelID - 1);//重置要取的套筒out
                        }
                        this.Invoke(new MethodInvoker(() =>
                        {
                            lbResult.Text = "通过";
                            lbResult.ForeColor = Color.White;
                            lbResult.Image = LiJu.Properties.Resources.pass;
                        }));
                        UpdateTip("点检返回PASS.");
                    }
                    else//电批打螺丝NG 弹品质页面
                    {
                        this.Invoke(new MethodInvoker(() =>
                        {
                            //打螺丝NG
                            lbResult.Text = "NG";
                            lbResult.ForeColor = Color.White;
                            lbResult.Image = LiJu.Properties.Resources.ng;

                        }));
                        UpdateTip("点检返回NG.");
                    }
                    break;
                }
                else//未获取到电批返回结果 
                {
                    Thread.Sleep(100);
                }
            }
        }

        //重新送钉判定 丢废螺丝后 才送同型号螺丝 
        private void BtReSongDing_Click(object sender, EventArgs e)
        {
            if (btStopWork.Visible && bCanReSongLuoSi)//作业中 才能重新送钉
            {
                //弹框 重新送钉判定
                formSongDingJudge.songDingJudgeModel.ProductSN = productTaskRecord.ProductSN;
                formSongDingJudge.songDingJudgeModel.WorkNo = productTaskRecord.WorkNo;
                formSongDingJudge.songDingJudgeModel.TaskID = productTaskRecord.TaskID;
      
                this.Invoke(new MethodInvoker(() =>
                {
                    formSongDingJudge.ShowDialog();
                }));

                //等判定完成
                while (true)
                {
                    if (formSongDingJudge.nState == 2 || formSongDingJudge.nState == 6)//不送 或 取消
                    {
                        return;
                    }
                    if (formSongDingJudge.nState > 0)
                    {
                        break;
                    }
                    Thread.Sleep(200);
                }

                this.Invoke(new MethodInvoker(() =>
                {
                    UpdateTip("请将废螺丝丢进废螺丝仓。");
                }));

                //感应到已丢废螺丝 在IO监控里判断
                while (true)
                {
                    if (formSongDingJudge.nState == 3)
                    {
                        break;
                    }
                    Thread.Sleep(200);
                }

                //发送同型号螺丝指令
                SongLuoSiSetOut(productTaskRecord.ScrewModel);

                UpdateTip(listScrewModel[productTaskRecord.ScrewModel - 1].Model + " 送钉中...");

                //监控实际送钉是否完成
                SongLuoSiReal(productTaskRecord.ScrewModel);

                //实际只有送钉成功 才会到此步 未送成功还在监控中
                Int64 nReturn = SongDingJudgeDbHelper.SongDingAgainUpdate(formSongDingJudge.songDingJudgeModel.LogID, 3);
                if (nReturn < 1)
                {
                    MessageBox.Show("Error:行93 SongDingAgainUpdate 重新送钉成功后更新数据库记录失败。");
                    return;
                }

                UpdateTip("请将电批移动到：" + String.Join(",", listdPositionNeed));
            }
            return;
        }

        /// <summary>
        /// 发送螺丝指令 螺丝机ID 从1开始
        /// </summary>
        /// <param name="nLuoSiJiID">螺丝机ID 从1开始</param>
        private bool SongLuoSiSetOut(int nLuoSiJiID)
        {
            bool bReturn = false;
            //送同型号螺丝指令
            if (UnifiedObj.DeviceConState[2] == 1)//有IO控制器
            {
                if (nLuoSiJiID == 1)//1号螺丝仓送钉
                {
                    bReturn = UnifiedObj.SetOutOpen(20);
                }
                else//2号螺丝仓送钉
                {
                    bReturn = UnifiedObj.SetOutOpen(21);
                }
                if (bReturn)
                {
                    UpdateTip(listScrewModel[nLuoSiJiID - 1].Model + "螺丝 送钉指令发送成功。");
                }
                else
                {
                    UpdateTip(listScrewModel[nLuoSiJiID - 1].Model + "螺丝 送钉指令执行失败。");
                }
            }
            return bReturn;
        }

        /// <summary>
        /// 监控实际送钉是否完成 更新页面螺丝库存 螺丝机ID 从1开始
        /// </summary>
        /// <param name="nLuoSiJiID">螺丝机ID 从1开始</param>
        /// <returns></returns>
        private void SongLuoSiReal(int nLuoSiJiID)
        {
            //监控到实际送钉成功
            while (true)
            {
                if (!btStopWork.Visible)//停止按钮点了后 不可见
                {
                    bIsWorking = false;
                    return;
                }
                bool bHaveSongDingIO = false;//实际送钉感应状态
                if (UnifiedObj.DeviceConState[2] == 1)//有IO控制器
                {
                    if (listScrewModel[nLuoSiJiID - 1].Id == 1)//1号螺丝仓送钉
                    {
                        bHaveSongDingIO = arrayInValue[4];
                    }
                    else//2号螺丝仓送钉
                    {
                        bHaveSongDingIO = arrayInValue[6];
                    }
                }
                else//无IO控制器 模拟感应送钉成功
                {
                    bHaveSongDingIO = true;
                }

                if (bHaveSongDingIO)
                {
                    //螺钉机送钉成功 剩余库存数量-1
                    int nReturn = ScrewDbHelper.ScrewModelUsed(Convert.ToInt32(listScrewModel[nLuoSiJiID - 1].Id));
                    if (nReturn < 1)
                    {
                        UpdateTip("Error:行560 ScrewModelUsed 螺钉机送钉成功后扣库存 更新数据库异常。");
                        bIsWorking = false;
                        return;
                    }

                    //更新页面螺钉库存
                    if (listScrewModel[nLuoSiJiID - 1].Id == 1)//当前螺丝用的1号仓螺丝
                    {
                        listScrewModel[0].CapacityNow -= 1;
                        this.Invoke(new MethodInvoker(() =>
                        {
                            lbLuoSiCang1.Text = listScrewModel[0].CapacityNow.ToString();
                            //库存报警
                            if (listScrewModel[0].CapacityNow <= arrayLuoSiWaringNum[0])
                            {
                                lbLuoSiCang1.ForeColor = Color.Gold;
                            }
                            else
                            {
                                lbLuoSiCang1.ForeColor = Color.White;
                            }
                        }));
                        if (UnifiedObj.DeviceConState[2] == 1)//有IO控制器
                        {
                            UnifiedObj.SetOutClose(20);//重置送钉OUT
                        }
                    }
                    else//当前螺丝用的2号仓螺丝
                    {
                        listScrewModel[1].CapacityNow -= 1;
                        this.Invoke(new MethodInvoker(() =>
                        {
                            lbLuoSiCang2.Text = listScrewModel[1].CapacityNow.ToString();
                            //库存报警
                            if (listScrewModel[1].CapacityNow <= arrayLuoSiWaringNum[1])
                            {
                                lbLuoSiCang2.ForeColor = Color.Gold;
                            }
                            else
                            {
                                lbLuoSiCang2.ForeColor = Color.White;
                            }
                        }));
                        if (UnifiedObj.DeviceConState[2] == 1)//有IO控制器
                        {
                            UnifiedObj.SetOutClose(21);//重置送钉OUT
                        }
                    }
                    UpdateTip(listScrewModel[nLuoSiJiID - 1].Model + "螺丝送钉成功。");
                    break;
                }
                if (UnifiedObj.DeviceConState[2] == 1)//有IO控制器
                {
                    Thread.Sleep(10);
                }
                else//无IO控制器 
                {
                    MessageBox.Show(listScrewModel[nLuoSiJiID - 1].Model + "螺丝送钉成功。");
                    Thread.Sleep(2000);
                    break;
                }
            }
        }

        //套筒1 缩回
        private void Label5_Click(object sender, EventArgs e)
        {
            SetTuiGanSuoHui(1);
        }

        /// <summary>
        /// 设置套筒缩回 断电默认弹出 nTaoTongNo 套筒序号1开始
        /// </summary>
        private void SetTuiGanSuoHui(int nTaoTongNo)
        {
            arrTuiGanSetOutState[nTaoTongNo - 1] = "1";
        }

        private void tbSN_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)//回车触发
            {
                Task.Run(() =>
                {
                    DoWork(tbSN.Text.Trim());
                });
            }
        }
    }


}
